"""
Bullet class and related functionality
"""
import pygame
import math
from typing import Tuple, Optional
from utils.constants import Direction, BulletType, CollisionType
from utils.config import BULLET_SPEED, WHITE, YELLOW, RED


class Bullet:
    """Bullet class for tank projectiles"""
    
    def __init__(self, x: int, y: int, direction: int, 
                 bullet_type: str = BulletType.NORMAL, owner: str = "player"):
        """
        Initialize bullet
        
        Args:
            x: X coordinate
            y: Y coordinate
            direction: Direction of movement
            bullet_type: Type of bullet
            owner: Owner of the bullet ("player" or "enemy")
        """
        self.x = x
        self.y = y
        self.direction = direction
        self.bullet_type = bullet_type
        self.owner = owner
        
        # Bullet properties
        self.speed = self._get_bullet_speed()
        self.damage = self._get_bullet_damage()
        self.size = self._get_bullet_size()
        self.color = self._get_bullet_color()
        
        # Movement
        self.dx, self.dy = self._get_direction_vector(direction)
        
        # Lifecycle
        self.lifetime = 3000  # milliseconds
        self.creation_time = pygame.time.get_ticks()
        self.active = True
        
        # Collision
        self.rect = pygame.Rect(x - self.size // 2, y - self.size // 2, 
                               self.size, self.size)
        
        # Trail effect
        self.trail = []
        self.max_trail_length = 5
    
    def _get_bullet_speed(self) -> int:
        """Get bullet speed based on type"""
        speed_map = {
            BulletType.NORMAL: BULLET_SPEED,
            BulletType.FAST: BULLET_SPEED * 1.5,
            BulletType.HEAVY: BULLET_SPEED * 0.7
        }
        return speed_map.get(self.bullet_type, BULLET_SPEED)
    
    def _get_bullet_damage(self) -> int:
        """Get bullet damage based on type"""
        damage_map = {
            BulletType.NORMAL: 1,
            BulletType.FAST: 1,
            BulletType.HEAVY: 2
        }
        return damage_map.get(self.bullet_type, 1)
    
    def _get_bullet_size(self) -> int:
        """Get bullet size based on type"""
        size_map = {
            BulletType.NORMAL: 4,
            BulletType.FAST: 3,
            BulletType.HEAVY: 6
        }
        return size_map.get(self.bullet_type, 4)
    
    def _get_bullet_color(self) -> Tuple[int, int, int]:
        """Get bullet color based on type and owner"""
        if self.owner == "player":
            color_map = {
                BulletType.NORMAL: YELLOW,
                BulletType.FAST: (255, 255, 0),  # Bright yellow
                BulletType.HEAVY: (255, 165, 0)  # Orange
            }
        else:
            color_map = {
                BulletType.NORMAL: RED,
                BulletType.FAST: (255, 100, 100),  # Light red
                BulletType.HEAVY: (139, 0, 0)  # Dark red
            }
        return color_map.get(self.bullet_type, WHITE)
    
    def _get_direction_vector(self, direction: int) -> Tuple[float, float]:
        """Get movement vector for direction"""
        vectors = {
            Direction.UP: (0, -1),
            Direction.DOWN: (0, 1),
            Direction.LEFT: (-1, 0),
            Direction.RIGHT: (1, 0)
        }
        return vectors.get(direction, (0, 0))
    
    def update(self, dt: float, screen_width: int, screen_height: int) -> bool:
        """
        Update bullet state
        
        Args:
            dt: Delta time in seconds
            screen_width: Screen width for boundary checking
            screen_height: Screen height for boundary checking
            
        Returns:
            True if bullet is still active
        """
        if not self.active:
            return False
        
        # Check lifetime
        current_time = pygame.time.get_ticks()
        if current_time - self.creation_time >= self.lifetime:
            self.active = False
            return False
        
        # Update trail
        self.trail.append((self.x, self.y))
        if len(self.trail) > self.max_trail_length:
            self.trail.pop(0)
        
        # Move bullet
        self.x += self.dx * self.speed * dt * 60
        self.y += self.dy * self.speed * dt * 60
        
        # Update collision rect
        self.rect.x = int(self.x - self.size // 2)
        self.rect.y = int(self.y - self.size // 2)
        
        # Check screen boundaries
        if (self.x < 0 or self.x > screen_width or 
            self.y < 0 or self.y > screen_height):
            self.active = False
            return False
        
        return True
    
    def render(self, screen: pygame.Surface):
        """
        Render bullet on screen
        
        Args:
            screen: Pygame surface to render on
        """
        if not self.active:
            return
        
        # Render trail
        self._render_trail(screen)
        
        # Render bullet
        pygame.draw.circle(screen, self.color, 
                          (int(self.x), int(self.y)), self.size)
        
        # Add glow effect for heavy bullets
        if self.bullet_type == BulletType.HEAVY:
            glow_color = (self.color[0], self.color[1], self.color[2], 100)
            pygame.draw.circle(screen, self.color, 
                              (int(self.x), int(self.y)), self.size + 2)
    
    def _render_trail(self, screen: pygame.Surface):
        """Render bullet trail effect"""
        if len(self.trail) < 2:
            return
        
        for i, (trail_x, trail_y) in enumerate(self.trail[:-1]):
            # Calculate alpha based on trail position
            alpha = int(255 * (i / len(self.trail)))
            trail_color = (*self.color[:3], alpha)
            
            # Draw trail segment
            pygame.draw.circle(screen, self.color, 
                              (int(trail_x), int(trail_y)), 
                              max(1, self.size - i))
    
    def get_collision_rect(self) -> pygame.Rect:
        """Get collision rectangle for bullet"""
        return self.rect.copy()
    
    def get_damage(self) -> int:
        """Get bullet damage"""
        return self.damage
    
    def get_owner(self) -> str:
        """Get bullet owner"""
        return self.owner
    
    def destroy(self):
        """Destroy bullet"""
        self.active = False
    
    def is_active(self) -> bool:
        """Check if bullet is active"""
        return self.active
    
    def check_collision(self, other_rect: pygame.Rect) -> bool:
        """
        Check collision with another rectangle
        
        Args:
            other_rect: Rectangle to check collision with
            
        Returns:
            True if collision detected
        """
        return self.rect.colliderect(other_rect)
    
    def get_position(self) -> Tuple[int, int]:
        """Get bullet position"""
        return int(self.x), int(self.y)